perm filename F4[CLS,LSP] blob sn#871204 filedate 1989-03-17 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	%Start Part 4 of 8 functi.tex
C00033 ENDMK
CāŠ—;
%Start Part 4 of 8 functi.tex
If a {\it doc-string\/} argument is present, it provides the
documentation for the method-combination type.

The functions {\bf method-combination-error} and {\bf
invalid-method-error} can be called from the body {\it forms\/} or
from functions called by the body {\it forms\/}.  The actions of these
two functions can depend on implementation-dependent dynamic variables
automatically bound before the generic function {\bf
compute-effective-method} is called.

Note that two methods with identical specializers, but with different
qualifiers, are not ordered by the algorithm described in Step 2 of
the method selection and combination process described in the section
``Method Selection and Combination.''  Normally the two methods play
different roles in the effective method because they have different
qualifiers, and no matter how they are ordered in the result of Step
2, the effective method is the same.  If the two methods play the same
role and their order matters, an error is signaled.  This happens as
part of the qualifier pattern matching in {\bf
define-method-combination}.

\label Values:

The value returned by the {\bf define-method-combination} macro is the new
method combination object.

\vfill\eject
\label Examples:

Most examples of the long form of {\bf define-method-combination} also
illustrate the use of the related functions that are provided as part
of the declarative method combination facility.

\screen!
;;; Examples of the short form of define-method-combination

(define-method-combination and :identity-with-one-argument t) 

(defmethod func and ((x class1) y) ...)

;;; The equivalent of this example in the long form is:

(define-method-combination and 
        (&optional (order ':most-specific-first))
        ((around (:around))
         (primary (and) :order order :required t))
  (let ((form (if (rest primary)
                  `(and ,@(mapcar #'(lambda (method)
                                      `(call-method ,method ()))
                                  primary))
                  `(call-method ,(first primary) ()))))
    (if around
        `(call-method ,(first around)
                      (,@(rest around)
                       (make-method ,form)))
        form)))

;;; Examples of the long form of define-method-combination

;The default method-combination technique
(define-method-combination standard ()
        ((around (:around))
         (before (:before))
         (primary () :required t)
         (after (:after)))
  (flet ((call-methods (methods)
           (mapcar #'(lambda (method)
                       `(call-method ,method ()))
                   methods)))
    (let ((form (if (or before after (rest primary))
                    `(multiple-value-prog1
                       (progn ,@(call-methods before)
                              (call-method ,(first primary)
                                           ,(rest primary)))
                       ,@(call-methods (reverse after)))
                    `(call-method ,(first primary) ()))))
      (if around
          `(call-method ,(first around)
                        (,@(rest around)
                         (make-method ,form)))
          form))))

;A simple way to try several methods until one returns non-nil
(define-method-combination or ()
        ((methods (or)))
  `(or ,@(mapcar #'(lambda (method)
                     `(call-method ,method ()))
                 methods)))

;A more complete version of the preceding
(define-method-combination or 
        (&optional (order ':most-specific-first))
        ((around (:around))
         (primary (or)))
  ;; Process the order argument
  (case order
    (:most-specific-first)
    (:most-specific-last (setq primary (reverse primary)))
    (otherwise (method-combination-error "~S is an invalid order.~@
    :most-specific-first and :most-specific-last are the possible values."
                                         order)))
  ;; Must have a primary method
  (unless primary
    (method-combination-error "A primary method is required."))
  ;; Construct the form that calls the primary methods
  (let ((form (if (rest primary)
                  `(or ,@(mapcar #'(lambda (method)
                                     `(call-method ,method ()))
                                 primary))
                  `(call-method ,(first primary) ()))))
    ;; Wrap the around methods around that form
    (if around
        `(call-method ,(first around)
                      (,@(rest around)
                       (make-method ,form)))
        form)))

;The same thing, using the :order and :required keyword options
(define-method-combination or 
        (&optional (order ':most-specific-first))
        ((around (:around))
         (primary (or) :order order :required t))
  (let ((form (if (rest primary)
                  `(or ,@(mapcar #'(lambda (method)
                                     `(call-method ,method ()))
                                 primary))
                  `(call-method ,(first primary) ()))))
    (if around
        `(call-method ,(first around)
                      (,@(rest around)
                       (make-method ,form)))
        form)))

;This short-form call is behaviorally identical to the preceding
(define-method-combination or :identity-with-one-argument t)
 
;Order methods by positive integer qualifiers
;:around methods are disallowed to keep the example small
(define-method-combination example-method-combination ()
        ((methods positive-integer-qualifier-p))
  `(progn ,@(mapcar #'(lambda (method)
                        `(call-method ,method ()))
                    (stable-sort methods #'<
                      :key #'(lambda (method)
                               (first (method-qualifiers method)))))))

(defun positive-integer-qualifier-p (method-qualifiers)
  (and (= (length method-qualifiers) 1)
       (typep (first method-qualifiers) '(integer 0 *))))

;;; Example of the use of :arguments
(define-method-combination progn-with-lock ()
        ((methods ()))
  (:arguments object)
  `(unwind-protect
       (progn (lock (object-lock ,object))
              ,@(mapcar #'(lambda (method)
                            `(call-method ,method ()))
                        methods))
     (unlock (object-lock ,object))))

\endscreen!

\vfill\eject
\label Remarks:

The {\bf :method-combination} option of {\bf defgeneric} is used to
specify that a generic function should use a particular method
combination type.  The argument to the {\bf :method-combination}
option is the name of a method combination type.
 
\label See Also: 

``Method Selection and Combination''

``Built-in Method Combination Types''

{\bf call-method}

{\bf method-qualifiers}

{\bf method-combination-error}

{\bf invalid-method-error} 

{\bf defgeneric}

\endcom



\begincom{defmethod}\ftype{Macro}

\label Purpose:

The macro {\bf defmethod} defines a method on a generic function.  

If {\tt (fboundp {\it function-specifier\/})} is {\bf nil}, a generic
function is created with default values for the argument precedence
order (each argument is more specific than the arguments to its right
in the argument list), for the generic function class (the class {\bf
standard-generic-function}), for the method class (the class {\bf
standard-method}), and for the method combination type (the standard
method combination type).  The lambda-list of the generic function is
congruent with the lambda-list of the method being defined; if the
{\bf defmethod} form mentions keyword arguments, the lambda-list of
the generic function will mention {\bf \&key} (but no keyword
arguments).  If {\it function-specifier\/} names a non-generic
function, a macro, or a special form, an error is signaled.

If a generic function is currently named by {\it
function-specifier\/}, where {\it function-specifier\/} is a symbol or
a list of the form {\tt (setf {\it symbol\/})}, the lambda-list of the
method must be congruent with the lambda-list of the generic function.
If this condition does not hold, an error is signaled.  See the
section ``Congruent Lambda-Lists for All Methods of a Generic
Function'' for a definition of congruence in this context.

\label Syntax:

\Defmac {defmethod} 
{\vtop{\hbox{function-specifier \star{\curly{method-qualifier\/}} specialized-lambda-list}
\hbox{\star{\curly{declaration $\vert$ documentation}} \star\form}}}
\Vskip1pc!\null
{\it function-specifier\/}::$=$ \curly{{\it symbol\/} $\vert$ {\tt (setf {\it symbol\/})}}
\Vskip1pc!\null
{\it method-qualifier\/}::$=$ {\it non-nil-atom}
\Vskip1pc!\null
\settabs\+\hskip\leftskip&\cr
\+&{\it specialized-lambda-list\/}::$=$ (&\star{\curly{var  $\vert$ {\rm (}var parameter-specializer-name\/{\rm )}}}  \cr
\+&&\ttbrac{{\opt} \star{\curly{var $\vert$ {\rm (}var \ttbrac{initform {\brac{supplied-p-parameter}} }{\rm )}}}}  \cr
\+&&\ttbrac{{\tt\&rest} {\it var\/}} \cr
\+&&{\tt [}{\key{}}&\star{\curly{var  $\vert$
{\rm (}\curly{var $\vert$ {\rm (}keyword var{\rm )}}
\ttbrac{initform \brac{supplied-p-parameter} }{\rm )}}}\cr
\+&&&\brac{\tt\&allow-other-keys} {\tt ]} \cr
\+&&\ttbrac{{\tt\&aux} \star{\curly{var $\vert$ {\rm (}var \brac{initform} {\rm )}}}} {\rm )} \cr
\Vskip1pc!\null
\+&{\it parameter-specializer-name\/}::$=$ {\it symbol} $\vert$ {\rm (}{\tt eql} {\it eql-specializer-form\/}{\rm )}\cr
\Vskip 1pc!

\vfill\eject
\label Arguments:

The {\it function-specifier\/} argument is a non-{\bf nil} symbol or a
list of the form {\tt (setf {\it symbol\/})}.  It names the generic
function on which the method is defined.

Each {\it method-qualifier\/} argument is an object that is used by
method combination to identify the given method.  A method qualifier
is a non-{\bf nil} atom.  The method combination type may further
restrict what a method qualifier may be.  The standard method
combination type allows for unqualified methods or methods whose sole
qualifier is the keyword {\bf :before}, the keyword {\bf
:after}, or the keyword {\bf :around}.

The {\it specialized-lambda-list\/} argument is like an ordinary
function lambda-list except that the names of required parameters can
be replaced by specialized parameters.  A specialized parameter is a
list of the form {\tt ({\it variable-name
parameter-specializer-name\/})}.  Only required parameters may be
specialized.  A parameter specializer name is a symbol that names a
class or {\tt (eql {\it eql-specializer-form\/})}.  The parameter
specializer name {\tt (eql {\it eql-specializer-form\/})} indicates
that the corresponding argument must be {\bf eql} to the object that
is the value of {\it eql-specializer-form\/} for the method to be
applicable.  If no parameter specializer name is specified for a given
required parameter, the parameter specializer defaults to the class
named {\bf t}.  See the section ``Introduction to Methods'' for
further discussion.

The {\it form\/} arguments specify the method body.
The body of the method is enclosed in an implicit block.  If
{\it function-specifier\/} is a symbol, this block bears the same name as the
generic function.  If {\it function-specifier\/} is a list of the form {\tt
(setf {\it symbol\/})}, the name of the block is {\it symbol}.  

\label Values:

The result of {\bf defmethod} is the method object.

\label Remarks:

The class of the method object that is created is that given by the 
method class option of the generic function on which the method is defined.

If the generic function already has a method that agrees with the
method being defined on parameter specializers and qualifiers, {\bf
defmethod} replaces the existing method with the one now being
defined.  See the section ``Agreement on Parameter Specializers and
Qualifiers'' for a definition of agreement in this context.

The parameter specializers are derived from the parameter specializer
names as described in the section ``Introduction to Methods.''

The expansion of the {\bf defmethod} macro ``refers to'' each
specialized parameter (see the description of {\bf ignore} in {\it
Common Lisp: The Language}, p. 160).  This includes parameters that
have an explicit parameter specializer name of {\bf t}.  This means
that a compiler warning does not occur if the body of the method does
not refer to a specialized parameter.  Note that a parameter that
specializes on {\bf t} is not synonymous with an unspecialized
parameter in this context.

\label See Also:

``Introduction to Methods''

``Congruent Lambda-Lists for All Methods of a Generic Function'' 

``Agreement on Parameter Specializers and Qualifiers''

\endcom


\begincom{describe}\ftype{Standard Generic Function}

\label Purpose:

The Common Lisp function {\bf describe} is replaced by a generic
function.  The generic function {\bf describe} prints information
about a given object on the standard output.

Each implementation is required to provide a method on the class {\bf
standard-object} and methods on enough other classes so as to ensure
that there is always an applicable method.  Implementations are free
to add methods for other classes.  Users can write methods for {\bf
describe} for their own classes if they do not wish to inherit an
implementation-supplied method.  These methods must conform to the
definition of {\bf describe} as specified in {\it Common Lisp: The
Language}.

\label Syntax:

\Defgen {describe} {object}

\label Method Signatures:

\Defmeth {describe} {({\it object\/} standard-object)}

\label Arguments:

The {\it object\/} argument may be any Common Lisp object. 

\label Values:

The generic function {\bf describe} returns no values.

\endcom
 

\begincom{documentation, (setf documentation)}\ftype{Standard Generic Function}

\label Purpose:

The Common Lisp function {\bf documentation} is replaced by a generic
function.  The generic function {\bf documentation} returns the
documentation string associated with the given object if it is
available; otherwise it returns {\bf nil}.

The generic function {\bf (setf documentation)} is used to update the
documentation.

\label Syntax:

\Defgen documentation {x {\opt} doc-type}

\Defgen {(setf documentation)} {new-value x {\opt} doc-type}

\label Method Signatures:

\Defmeth {documentation} {({\it method\/} standard-method) \&optional {\it doc-type}}

\Defmeth {(setf documentation)} {\vtop{\hbox{{\it new-value\/} ({\it method\/} standard-method)}
\hbox{\&optional {\it doc-type}}}}

\Defmeth {documentation} {\vtop{\hbox{({\it generic-function\/} standard-generic-function)} \hbox{\&optional {\it doc-type}}}}

\Defmeth {(setf documentation)} {\vtop{\hbox{{\it new-value\/}}
\hbox{({\it generic-function\/} standard-generic-function)} 
\hbox{\&optional {\it doc-type}}}}

\Defmeth {documentation} {({\it class\/} standard-class) \&optional {\it doc-type}}

\Defmeth {(setf documentation)} {\vtop{\hbox{{\it new-value\/} ({\it class\/} standard-class)}
\hbox{\&optional {\it doc-type}}}}

\Defmeth {documentation} {\vtop{\hbox{({\it method-combination\/} method-combination)} \hbox{\&optional {\it doc-type}}}}

\Defmeth {(setf documentation)} {\vtop{\hbox{{\it new-value\/}}
\hbox{({\it method-combination\/} method-combination)}
\hbox{\&optional {\it doc-type}}}}

\Defmeth {documentation} {\vtop{\hbox{({\it slot-description\/} 
standard-slot-description)} \hbox{\&optional {\it doc-type}}}}

\Defmeth {(setf documentation)} {\vtop{\hbox{{\it new-value\/}}
\hbox{({\it slot-description\/} standard-slot-description)}
\hbox{\&optional {\it doc-type}}}}

\Defmeth {documentation} {({\it symbol\/} symbol) \&optional {\it doc-type}}

\Defmeth {(setf documentation)} {\vtop{\hbox{{\it new-value\/} ({\it symbol\/} symbol)}
\hbox{\&optional {\it doc-type}}}}

\Defmeth {documentation} {({\it list\/} list) \&optional {\it doc-type}}

\Defmeth {(setf documentation)} {\vtop{\hbox{{\it new-value\/} ({\it list\/} list)}
\hbox{\&optional {\it doc-type}}}}

\label Arguments:

The first argument of {\bf documentation} is either a symbol, a
function specifier list of the form {\tt (setf {\it symbol\/})}, a
method object, a class object, a generic function object, a method
combination object, or a slot description object.

\beginlist

\item{\bull}
If the first argument is a method object, a class object, a generic
function object, a method combination object, or a slot description
object, the second argument must not be supplied, or an error is
signaled.

\item{\bull} 
If the first argument is a symbol or a list of the form
{\tt (setf {\it symbol\/})}, the second argument must be
supplied.

\itemitem{--}
The forms {\tt (documentation {\it symbol\/} 'function)} and
{\tt (documentation '(setf {\it symbol\/}) 'function)} return the
documentation string of the function, generic function, special form, or
macro named by the symbol or list.

\itemitem{--}
The form {\tt (documentation {\it symbol\/} 'variable)} returns the
documentation string of the special variable or constant named by the
symbol.

\itemitem{--}
The form {\tt (documentation {\it symbol\/} 'structure)} returns the
documentation string of the {\bf defstruct} structure named by the
symbol.

\itemitem{--}
The form {\tt (documentation {\it symbol\/} 'type)} returns the documentation
string of the class object named by the symbol, if there is such a
class.   If there is no such class, it returns the documentation string
of the type specifier named by the symbol. 

\itemitem{--}
The form {\tt (documentation {\it symbol\/} 'setf)} returns the documentation
string of the {\bf defsetf} or {\bf define-setf-method} definition
associated with the symbol.

\itemitem{--}
The form {\tt (documentation {\it symbol\/} 'method-combination)} returns the
documentation string of the method combination type named by the
symbol.  

\item{}
An implementation may extend the set of symbols that are acceptable as
the second argument.  If a symbol is not recognized as an acceptable
argument by the implementation, an error must be signaled.

\endlist

\label Values:

The documentation string associated with the given object is returned
unless none is available, in which case {\bf documentation} returns
{\bf nil}.

\endcom



\begincom{ensure-generic-function}\ftype{Function}

\label Purpose:

The function {\bf ensure-generic-function} is used to define a
globally named generic function with no methods or to specify or
modify options and declarations that pertain to a globally named
generic function as a whole.

If {\tt (fboundp {\it function-specifier\/})} is {\bf nil}, a new
generic function is created.  If {\tt (symbol-function {\it
function-specifier\/})} is a non-generic function, a macro, or a
special form, an error is signaled.

If {\it function-specifier\/} specifies a generic function that has a
different value for any of the following arguments, the generic
function is modified to have the new value: {\bf
:argument-precedence-order}, {\bf :declare}, {\bf :documentation},
{\bf :method-combination}.

%End Part 4 of 8 functi.tex